#include "../userprog/syscall.h"

/*/======== Function that returns the number of taken seats in the theater ========*/
int getNumTakenSeats()
{	
	int SCREENING_ROOM_CAPACITY;
	SCREENING_ROOM_CAPACITY = CreateMV(1, "SCREENING_ROOM_CAPACITY", 23);
	
	return GetMV(SCREENING_ROOM_CAPACITY,0) - getNumAvailableSeats();
}

/*/======== Function that returns the number of available seats in the theater ========*/
int getNumAvailableSeats()
{
	int SCREENING_ROOM_ROWS;
	int r;
	int total = 0;
	
	SCREENING_ROOM_ROWS = CreateMV(1,"SCREENING_ROOM_ROWS",19);
	
	for(r = 0; r < GetMV(SCREENING_ROOM_ROWS,0); r++)
	{
		total += getNumFreeSeats(r);
	}
	
	return total;
}

/*/======== Function that returns the number of free seats in a screening room row ========*/
int getNumFreeSeats(int row)
{
	int SCREENING_ROOM_COLS;
	int SCREENING_ROOM_ROWS;
	int screeningRoomSeat;
	int freeSeats = 0;
	int col;
	SCREENING_ROOM_ROWS = CreateMV(1,"SCREENING_ROOM_ROWS",19);
	SCREENING_ROOM_COLS = CreateMV(1, "SCREENING_ROOM_COLS", 19);
	screeningRoomSeat = CreateMV(GetMV(SCREENING_ROOM_ROWS,0),"screeningRoomSeat",17);
	for(col = 0; col < GetMV(SCREENING_ROOM_COLS,0); col++)
	{
		if(GetMV(GetMV(screeningRoomSeat, row), col) < 0)
		{
			freeSeats++;
		}
	}
	return freeSeats;
}

/*/======== Movie Technician Function ========*/
void main()
{
	int myIndex;
	int ticketCount;
	int theaterCount;
	
	int i0;

	
	/*Shared Data*/
	int PRINT_DEBUG_MESSAGES;
	int PRINT_OUTPUT_MESSAGES;
	int movieTechLock;
	int movieTechCondition;
	int ticketCountBoxLock;
	int ticketCountBox;
	int screeningRoomLock;
	int movieStateLock;
	int MOVIE_STATE;
	int IN_PROGRESS;
	int movieNumber;
	int ROOM_EMPTYING;
	int movieInProgressLock;
	int movieInProgressCondition;
	int ROOM_EMPTY;
	
	/*Acquire Shared Data*/
	PRINT_DEBUG_MESSAGES = CreateMV(1,"PRINT_DEBUG_MESSAGES",20);
	PRINT_OUTPUT_MESSAGES = CreateMV(1,"PRINT_OUTPUT_MESSAGES", 21);
	movieTechLock = CreateLock("movieTechLock",13);
	movieTechCondition = CreateCondition("movieTechCondition",18);
	ticketCountBoxLock = CreateLock("ticketCountBoxLock",18);
	screeningRoomLock = CreateLock("screeningRoomLock",17);
	movieInProgressLock = CreateLock("movieInProgressLock",19);
	movieInProgressCondition = CreateCondition("movieInProgressCondition",24);
	ticketCountBox = CreateMV(1,"ticketCountBox",14);
	movieStateLock = CreateLock("movieStateLock",14);
	MOVIE_STATE = CreateMV(1,"MOVIE_STATE",11);
	ROOM_EMPTY = CreateMV(1,"ROOM_EMPTY",10);
	IN_PROGRESS = CreateMV(1,"IN_PROGRESS",11);
	ROOM_EMPTYING = CreateMV(1,"ROOM_EMPTYING",13);
	movieNumber = CreateMV(1,"movieNumber",11);
	
	myIndex = 0;
	
	
	
	
	if(GetMV(PRINT_DEBUG_MESSAGES,0)) FPrint("MovieTechnician: created\n", 26, 0, 0);
	
	while(1){
	
		/*/Wait for Manager to acknowledge movie is sold out*/
		if(GetMV(PRINT_DEBUG_MESSAGES,0)) FPrint("MovieTechnician: acquiring movieTechLock\n", 42, 0, 0);
		AcquireLock(movieTechLock);
		if(GetMV(PRINT_DEBUG_MESSAGES,0)) FPrint("MovieTechnician: waiting for Manager to signal\n", 48, 0, 0);
		WaitCondition(movieTechCondition, movieTechLock);
		if(GetMV(PRINT_DEBUG_MESSAGES,0)) FPrint("MovieTechnician: signalled out of movieTechLock\n", 49, 0, 0);
		ReleaseLock(movieTechLock);

			
			
			if(GetMV(PRINT_DEBUG_MESSAGES,0))
				FPrint("MovieTechnician waiting for theater to fill\n", 45, 0, 0);
				
			
				
			/*/ Wait for everyone to be seated in the theater*/
			do{		
				Yield();
				/*/Check current ticket count*/
				AcquireLock(ticketCountBoxLock);			
				ticketCount = ticketCountBox;		
				ReleaseLock(ticketCountBoxLock);
				
				/*/Check number of customers seated in the screening room*/
				AcquireLock(screeningRoomLock);
				theaterCount = getNumTakenSeats();
				ReleaseLock(screeningRoomLock);
				
				if(GetMV(PRINT_DEBUG_MESSAGES,0))
					FPrint("MovieTechnician: ticketCount = %d, theaterCount = %d\n", 54, 2, ticketCount*100 + theaterCount);
			
			}while(ticketCount > theaterCount);

			if(GetMV(PRINT_DEBUG_MESSAGES,0))
				FPrint("MovieTechnician changing movie status to in progress\n", 54, 0, 0);
			/*/Change the movie status to in progress*/
			AcquireLock(movieStateLock);
			MOVIE_STATE = IN_PROGRESS;
			movieNumber++;
			if(GetMV(PRINT_DEBUG_MESSAGES,0)) FPrint("MovieTechnician: Starting movie %d with %d customers in theater\n", 65, 2, movieNumber*100 + theaterCount);
			ReleaseLock(movieStateLock);
			
			AcquireLock(ticketCountBoxLock);			
			ticketCountBox = 0;		
			ReleaseLock(ticketCountBoxLock);
			
			if(GetMV(PRINT_DEBUG_MESSAGES,0)) FPrint("MovieTechnician yeilding\n", 26, 0, 0);
			if(GetMV(PRINT_OUTPUT_MESSAGES,0)) FPrint("The MovieTechnician has started the movie.\n", 44, 0, 0);
				
			for(i0 = 0;i0 < ((RandInt() % 101) + 200);i0++){
				Yield();
			}
			
			if(GetMV(PRINT_DEBUG_MESSAGES,0)) FPrint("MovieTechnician: Finished movie %d with %d customers in theater\n", 65, 2, movieNumber*100 + theaterCount);
			if(GetMV(PRINT_OUTPUT_MESSAGES,0)) FPrint("The MovieTechnician has ended the movie.\n", 42, 0, 0);
			
			/*/Change the movie status to in progress*/
			AcquireLock(movieStateLock);
			MOVIE_STATE = ROOM_EMPTYING;
			ReleaseLock(movieStateLock);
			
			if(GetMV(PRINT_DEBUG_MESSAGES,0))
				FPrint("MovieTechnician telling customers to leave\n", 44, 0, 0);
			AcquireLock(movieInProgressLock);
			BroadcastCondition(movieInProgressCondition, movieInProgressLock);
			ReleaseLock(movieInProgressLock);
			
			if(GetMV(PRINT_OUTPUT_MESSAGES,0)) FPrint("The MovieTechnician has told all customers to leave the theater room.\n", 71, 0, 0);
			if(GetMV(PRINT_DEBUG_MESSAGES,0)) FPrint("MovieTechnician waiting for screening room to empty\n", 53, 0, 0);
			do{
				Yield();
				/*/Check number of customers seated in the screening room*/
				AcquireLock(screeningRoomLock);
				theaterCount = getNumTakenSeats();
				ReleaseLock(screeningRoomLock);
				
			}while(theaterCount > 0);
			
			/*/Change the movie status to in progress*/
			AcquireLock(movieStateLock);
			if(GetMV(PRINT_DEBUG_MESSAGES,0)) FPrint("MovieTechnician setting MOVIE_STATE to ROOM_EMPTY\n", 51, 0, 0);
			MOVIE_STATE = ROOM_EMPTY;
			ReleaseLock(movieStateLock);
		
	}
}